package com.sdhs.paas.gateway.filter;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import com.alibaba.fastjson.JSON;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.sdhs.paas.authclient.jwt.ServiceAuthUtil;
import com.sdhs.paas.authclient.jwt.UserAuthUtil;
import com.sdhs.paas.authshare.common.msg.TokenErrorResponse;
import com.sdhs.paas.authshare.context.BaseContextHandler;
import com.sdhs.paas.authshare.util.jwt.IJWTInfo;
import com.sdhs.paas.authshare.util.jwt.JWTInfo;
import com.sdhs.paas.gateway.model.JwtInfoVO;
import com.sdhs.paas.gateway.util.JSONUtil;
import com.sdhs.paas.sdk.core.logger.Logger;
import com.sdhs.paas.sdk.core.logger.LoggerFactory;

/**
 * ${DESCRIPTION}
 *
 * @author kjc
 * @create 2017-06-23 8:25
 */
@Component
public class AdminAuthenticationFilter extends ZuulFilter {
	private static Logger logger = LoggerFactory.getLogger(AdminAuthenticationFilter.class);
	
	@Autowired
	private UserAuthUtil userAuthUtil;
	
	@Autowired
	private ServiceAuthUtil serviceAuthUtil;
	
	@Value("${gate.ignore.startWith}")
	private String startWith;

	@Value("${zuul.prefix}")
	private String zuulPrefix;

	@Override
	public String filterType() {
		return "pre";
	}

	@Override
	public int filterOrder() {
		return 1;
	}

	@Override
	public boolean shouldFilter() {
		return true;
	}

	@Override
	public Object run() {
		logger.info("start user token authenticationFilter");
		RequestContext ctx = RequestContext.getCurrentContext();
		HttpServletRequest request = ctx.getRequest();
		// 去除统一的请求前缀/api,如果请求url为/api/jwt/token,截取之后的路径为/jwt/token
		final String requestUri = request.getRequestURI().substring(zuulPrefix.length());
		final String method = request.getMethod();
		logger.info("requestUri:" + requestUri + ";method:" + method);
		BaseContextHandler.setToken(null);
		// 不进行拦截的地址,白名单，不进行过滤的请求url
		if (isStartWith(requestUri)) {
			return null;
		}
		 IJWTInfo user = null;
		try {
			 user = getJWTUser(request, ctx);
			 ctx.addZuulRequestHeader("requserid", JSONUtil.obj2json(new JwtInfoVO(user.getUniqueName(),user.getId(),user.getName())));
		} catch (Exception e) {
			logger.error("Token is error or expired", e.getMessage());
			setFailedRequest(JSON.toJSONString(new TokenErrorResponse("Token is error or expired")), 200);
			return null;
		}
		// List<PermissionInfo> permissionIfs =
		// userService.getAllPermissionInfo();
		// // 判断资源是否启用权限约束
		// Stream<PermissionInfo> stream = getPermissionIfs(requestUri, method,
		// permissionIfs);
		// List<PermissionInfo> result = stream.collect(Collectors.toList());
		// PermissionInfo[] permissions = result.toArray(new
		// PermissionInfo[]{});
		// if (permissions.length > 0) {
		// checkUserPermission(permissions, ctx, user);
		// }
		// 申请客户端密钥头
		// ctx.addZuulRequestHeader(serviceAuthConfig.getTokenHeader(),
		// serviceAuthUtil.getClientToken());
		return null;
	}

	/**
	 * 返回session中的用户信息
	 *
	 * @param request
	 * @param ctx
	 * @return
	 */
	private IJWTInfo getJWTUser(HttpServletRequest request, RequestContext ctx) throws Exception {
		String authToken = request.getHeader(userAuthUtil.getTokenHeader());
		if (StringUtils.isBlank(authToken)) {
			authToken = request.getParameter("token");
		}
		ctx.addZuulRequestHeader(userAuthUtil.getTokenHeader(), authToken);
		BaseContextHandler.setToken(authToken);
		return userAuthUtil.getInfoFromToken(authToken);
	}

	/**
	 * URI是否以什么打头
	 *
	 * @param requestUri
	 * @return
	 */
	private boolean isStartWith(String requestUri) {
		boolean flag = false;
		for (String s : startWith.split(",")) {
			if (requestUri.startsWith(s)) {
				return true;
			}
		}
		return flag;
	}

	/**
	 * 网关抛异常
	 *
	 * @param body
	 * @param code
	 */
	private void setFailedRequest(String body, int code) {
		// log.debug("Reporting error ({}): {}", code, body);
		RequestContext ctx = RequestContext.getCurrentContext();
		ctx.setResponseStatusCode(code);
		if (ctx.getResponseBody() == null) {
			ctx.setResponseBody(body);
			ctx.setSendZuulResponse(false);
		}
	}

}
